{% extends 'base/base.html' %}
{% load static %}
{% load humanize %}
{% load custom_tags %}
{% block title %}
Scan history
{% endblock title %}

{% block custom_js_css_link %}
<link rel="stylesheet" type="text/css" href="{% static 'plugins/table/datatable/datatables.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'assets/css/forms/theme-checkbox-radio.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'plugins/table/datatable/dt-global_style.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'plugins/table/datatable/custom_dt_custom.css' %}">
<link href="{% static 'assets/css/dashboard/dash_1.css' %}" rel="stylesheet" type="text/css" />
<script src="{% static 'plugins/sweetalerts/promise-polyfill.js' %}"></script>
<link href="{% static 'plugins/sweetalerts/sweetalert2.min.css' %}" rel="stylesheet" type="text/css" />
<link href="{% static 'plugins/sweetalerts/sweetalert.css' %}" rel="stylesheet" type="text/css" />
<link href="{% static 'assets/css/components/custom-sweetalert.css' %}" rel="stylesheet" type="text/css" />
<link href="{% static 'assets/css/components/custom-modal.css' %}" rel="stylesheet" type="text/css" />
<link href="{% static 'assets/css/elements/custom-tree_view.css' %}" rel="stylesheet" type="text/css" />
<link href="{% static 'plugins/lightbox/css/lightbox.css' %}" rel="stylesheet" />
<script src="{% static 'custom/custom.js' %}"></script>
{% endblock custom_js_css_link %}

{% block breadcrumb_title %}
Detailed Scan for {{history.domain_name}}
{% endblock breadcrumb_title %}


{% block main_content %}
<div class="col-xl-12 col-lg-12 col-md-12 col-sm-12 col-12 layout-px-spacing">
    <div class="row layout-top-spacing">
        <div class="col-xl-3 col-lg-3 col-md-6 col-sm-6 col-12 mt-2">
            <div class="widget widget-activity-four">
                <div class="widget-heading">
                    <h5>Recent Activities</h5>
                </div>
                <div class="widget-content">
                    <div class="mt-container mx-auto">
                        <div class="timeline-line">
                            {% for activity in scan_activity %}
                            <div class="item-timeline {% if activity.status == 0 %}timeline-success {% elif activity.status == 1 %}timeline-warning{% elif activity.status == 2 %}timeline-success{% endif %}">
                                <div class="t-dot" data-original-title="" title="">
                                </div>
                                <div class="t-text">
                                    <b>{{activity.title}}</b>
                                    <span class="badge {% if activity.status == 0 %}badge-success {% elif activity.status == 1 %}badge-warning{% elif activity.status == 2 %}badge-success{% endif %}">
                                        {% if activity.status == 0 %}&nbsp;Failed&nbsp;
                                        {% elif activity.status == 1 %}&nbsp;In progress&nbsp;
                                        {% elif activity.status == 2 %}&nbsp;Completed&nbsp;
                                        {% endif %}
                                    </span>
                                    <p class="t-time">{{activity.time|naturaltime}}</p>
                                </div>
                            </div>
                            {% endfor %}
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-xl-3 col-lg-3 col-md-6 col-sm-6 col-12 mt-2">
            <div class="widget widget-one_hybrid">
                <div class="widget-heading">
                    <div class="w-icon">
                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-globe">
                            <circle cx="12" cy="12" r="10"></circle>
                            <line x1="2" y1="12" x2="22" y2="12"></line>
                            <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
                        </svg>
                    </div>
                    &nbsp;
                    <h2 class="text-warning">{{subdomain_count}}</h2>
                    <h6 class="">Subdomains Discovered</h6>
                </div>
                <div class="widget-content">
                    Total Alive Subdomains: <b class="text-info">{{alive_count}}</b>
                </div>
            </div>
        </div>
        <div class="col-xl-3 col-lg-3 col-md-6 col-sm-6 col-12 mt-2">
            <div class="widget widget-one_hybrid">
                <div class="widget-heading">
                    <div class="w-icon">
                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link">
                            <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
                            <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
                        </svg>
                    </div>
                    &nbsp;
                    <h2 class="text-warning">{{endpoint_count}}</h2>
                    <h6 class="">Endpoints</h6>
                </div>
                <div class="widget-content">
                    Total Alive Endpoints: <b class="text-info">{{endpoint_alive_count}}</b>
                </div>
            </div>
        </div>
        <div class="col-xl-3 col-lg-3 col-md-6 col-sm-6 col-12 mt-2">
            <div class="widget widget-one_hybrid">
                <div class="widget-heading">
                    <div class="w-icon">
                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-globe">
                            <circle cx="12" cy="12" r="10"></circle>
                            <line x1="2" y1="12" x2="22" y2="12"></line>
                            <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
                        </svg>
                    </div>
                    &nbsp;
                    <h2 class="text-danger">{{subdomain_takeover}}</h2>
                    <h6 class="">Subdomain Takeover</h6>
                </div>
                <div class="widget-content">
                    &nbsp;
                </div>
            </div>
        </div>
    </div>
    <div class="row layout-top-spacing mb-4">
        <div class="col-xl-12 col-lg-12 col-md-12 col-sm-12 col-12">
            <div class="widget-content widget-content-area br-6">
                <h5 class="text-info">Subdomains Discovered</h5>
                {% if subdomain_count %}
                <a href="../export/subdomains/{{scan_history_id}}" class="btn btn-info mb-2 mt-4">Export Subdomains(txt format)</a>
                <a href="../export/urls/{{scan_history_id}}" class="btn btn-info mb-2 mt-4">Export URLs(txt format)</a>
                {% endif %}
                <div class="table-responsive mb-4 mt-4">
                    <table id="subdomain_scan_results" class="multi-table table table-striped table-bordered table-hover" style="width:100%">
                        <thead>
                            <tr>
                                <th>Subdomain</th>
                                <th>IP Address</th>
                                <th>Status</th>
                                <th>Ports</th>
                                <th class="text-center">Takeover</th>
                                <th>Content Length</th>
                                <th>Page Title</th>
                                <th>Technology</th>
                                <th>Screenshot</th>
                                <th>Directories</th>
                            </tr>
                        </thead>
                    </table>
                </div>
            </div>
        </div>
    </div>
    {% if history.scan_type.fetch_url %}
    <div class="row mb-4">
        <div class="col-xl-12 col-lg-12 col-md-12 col-sm-12 col-12">
            <div class="widget-content widget-content-area br-6 layout-top-spacing">
                <h5 class="text-info">Endpoints</h5>
                {% if endpoint_count %}
                <a href="../export/endpoints/{{scan_history_id}}" class="btn btn-info mb-2 mt-4">Export Endpoints(txt format)</a>
                {% endif %}
                <div class="table-responsive mb-4 mt-4">
                    <table class="multi-table table table-striped table-bordered table-hover" style="width:100%" id="endpoint_results">
                        <thead>
                            <tr>
                                <th>Endpoint</th>
                                <th>HTTP Status</th>
                                <th>Content Type</th>
                                <th>Content Length</th>
                                <th>Page Title</th>
                            </tr>
                        </thead>
                    </table>
                </div>
            </div>
        </div>
    </div>
    {% endif %}
</div>
{% endblock main_content %}


{% block page_level_script %}
<script src="{% static 'plugins/table/datatable/datatables.js' %}"></script>
<script src="{% static 'plugins/sweetalerts/sweetalert2.min.js' %}"></script>
<script src="{% static 'plugins/sweetalerts/custom-sweetalert.js' %}"></script>
<script src="{% static 'plugins/lightbox/js/lightbox.js' %}"></script>
<script src="{% static 'assets/js/dashboard/dash_1.js' %}"></script>
<script src="{% static 'custom/custom.js' %}"></script>
<script src="//cdn.datatables.net/1.10.16/js/dataTables.bootstrap4.min.js"></script>

<script type="text/javascript">
// collapse sidebar only when screen size is > md (bootstrap), for smaller screen theme already hides the sidebar
if ($(window).width() > 992) {
    $( document ).ready(function() {
        $("html, body").addClass("sidebar-noneoverflow");
        $("#container").addClass("sidebar-closed");
        $("header").addClass("expand-header");
    });
}
function fetch_http_headers(id, http_header_path, screenshot_path){
    $('#screenshot'+id).attr('src', '/media/'+screenshot_path);
    fetch('/media/'+http_header_path)
    .then(response => response.text())
    .then(text => $("#tabsModal"+id+" #txt-file-content").text(text));
}
</script>
<script>
$(document).ready(function() {
    var scan_history_table = $('#subdomain_scan_results').DataTable({
        "oLanguage": {
            "oPaginate": { "sPrevious": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>', "sNext": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>' },
            "sInfo": "Showing page _PAGE_ of _PAGES_",
            "sSearch": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>',
            "sSearchPlaceholder": "Search...",
            "sLengthMenu": "Results :  _MENU_",
        },
        "stripeClasses": [],
        "lengthMenu": [20, 40, 60, 100],
        "pageLength": 20,
        'serverSide': true,
        "ajax": '/start_scan/api/scanHistory/?scan_id={{scan_history_id}}&format=datatables',
        "order": [[ 5, "desc" ]],
        "columns": [
            {'data': 'subdomain'},
            {'data': 'ip_address'},
            {'data': 'http_status'},
            {'data': 'open_ports'},
            {'data': 'takeover'},
            {'data': 'content_length', 'searchable': false},
            {'data': 'page_title'},
            {'data': 'technology_stack'},
            {'data': 'screenshot_path', 'searchable': false},
            {'data': 'directory_json'},
            {'data': 'http_url'},
            {'data': 'is_ip_cdn'},
            {'data': 'cname'},
        ],
        "columnDefs": [
            {
                "targets": [ 10, 11],
                "visible": false,
                "searchable": false,
            },
            {
                "targets": [ 12 ],
                "visible": false,
                "searchable": true,
            },
            {
                "render": function ( data, type, row ) {
                    if (row['http_url']) {
                        if (row['cname']) {
                            return `<a href="`+row['http_url']+`" class="text-info" target="_blank">`+data+`</a><br><span class="text-dark">CNAME<span class="text-warning"> ❯ </span>` + row['cname'].replace(',', '<span class="text-warning"> ❯ </span>')+`</span>`;
                        }
                        return `<a href="`+row['http_url']+`" class="text-info" target="_blank">`+data+`</a><br>`;
                    }
                    return `<a href="https://`+data+`" class="text-info" target="_blank">`+data+`</a>`;
                },
                "targets": 0
            },
            {
                "render": function ( data, type, row ) {
                    // display badge based on http status
                    // green for http status 2XX, orange for 3XX and warning for everything else
                    if (data) {
                        if (row['is_ip_cdn']) {
                            return `<span class='badge badge-pills badge-warning bs-tooltip' title="CDN IP Address">` + data + `</span>`
                        }
                        return `<span class='badge badge-pills badge-info'>` + data + `</span>`
                    }
                    else {
                        return '';
                    }
                },
                "targets": 1,
            },
            {
                "render": function ( data, type, row ) {
                    // display badge based on http status
                    // green for http status 2XX, orange for 3XX and warning for everything else
                    if (data >= 200 && data < 300) {
                        return "<span class='badge badge-pills badge-success'>"+data+"</span>";
                    }
                    else if (data >= 300 && data < 400) {
                        return "<span class='badge badge-pills badge-warning'>"+data+"</span>";
                    }
                    else if (data == 0){
                        // datatable throws error when no data is returned
                        return "";
                    }
                    return `<span class='badge badge-pills badge-danger'>`+data+`</span>`;
                },
                "targets": 2,
            },
            {
                "render": function ( data, type, row ) {
                    // display badge based on http status
                    // green for http status 2XX, orange for 3XX and warning for everything else
                    return span_values(data, "info");
                },
                "targets": 3,
            },
            {
                "render": function ( data, type, row ) {
                    // for takeover
                    if (data){
                        return `<div class="t-dot bg-danger" data-toggle="tooltip" data-placement="top" data-original-title=" Potentially vulnerable via `+data+`"></div>`;
                    }
                    return `<div class="t-dot bg-success" data-toggle="tooltip" data-placement="top" data-original-title="Takeover Not Possible"></div>`;
                },
                "targets": 4,
            },
            {
                "render": function ( data, type, row ) {
                    if (data){
                        return htmlEncode(data);
                    }
                    return "";
                },
                "targets": 6,
            },
            {
                "render": function ( data, type, row ) {
                    if (data){
                        return span_values(data, "info");
                    }
                    return "";
                },
                "targets": 7,
            },
            {
                "render": function ( data, type, row ) {
                    if (data){
                        //return lightbox with caption as http link
                        return `<a href="/media/`+data+`" data-lightbox="screenshots" data-title="&lt;a target='_blank' href='`+row['http_url']+`'&gt;&lt;h3 style=&quot;color:white&quot;&gt;`+row['subdomain']+`&lt;/h3&gt;&lt;/a&gt;"><img src="/media/`+data+`" class="img-fluid rounded mb-4 mt-4"></a>`;
                    }
                    return "";
                },
                "targets": 8,
            },
            {
                "render": function ( data, type, row ) {
                    if (data) {
                        // TODO: this could be done better
                        data = JSON.parse(data);
                        main_url = Object.keys(data)[0];
                        var json_obj = data[main_url];
                        var html_treeview = `<ul class="file-tree">`;
                        for(var i = 0; i < json_obj.length; i++)
                        {
                            if(json_obj[i].status==200)
                            {
                                var path = json_obj[i].path;
                                // id path has / the its a directory else consider as file
                                if (path.substr(path.length - 1) == '/') {
                                    html_treeview += `<li class="file-tree-empty-folder"><a href="` + main_url + path + `" target="_blank">` + path + `</a></li>`;
                                }
                                else {
                                    html_treeview += `<li id='filePath'><a href="` + main_url + path + `" target="_blank">` + path + `</a></li>`;
                                }
                            }
                        }
                        html_treeview += `</ul>`;
                        return html_treeview;
                    }
                    return '';
                },
                "targets": 9,
            },
        ],
        drawCallback: function () {
            $('.t-dot').tooltip({ template: '<div class="tooltip status" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>' })
            $('.dataTables_wrapper table').removeClass('table-striped');
            $('.badge').tooltip({ template: '<div class="tooltip status" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>' })
            $('.dataTables_wrapper table').removeClass('table-striped');
        },
        initComplete: function( settings, json ) {
            var script = document.createElement("script");
            script.src = "/staticfiles/plugins/treeview/custom-jstree.js";
            script.type = "text/javascript";
            document.getElementsByTagName("head")[0].appendChild(script);
        }
    });
});
</script>
<script type="text/javascript">
$(document).ready(function() {
    $('#endpoint_results').DataTable({
        "oLanguage": {
            "oPaginate": { "sPrevious": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>', "sNext": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>' },
            "sInfo": "Showing page _PAGE_ of _PAGES_",
            "sSearch": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>',
            "sSearchPlaceholder": "Search...",
            "sLengthMenu": "Results :  _MENU_",
        },
        "stripeClasses": [],
        "lengthMenu": [20, 40, 60, 100],
        "pageLength": 20,
        'serverSide': true,
        "ajax": '/start_scan/api/listEndpoints/?url_of={{scan_history_id}}&format=datatables',
        "order": [[ 3, "desc" ]],
        "columns": [
            {'data': 'http_url'},
            {'data': 'http_status'},
            {'data': 'content_type'},
            {'data': 'content_length'},
            {'data': 'page_title'},
        ],
        "columnDefs": [
            {
                "render": function ( data, type, row ) {
                    // in the endpoint section, there is no point of displaying fully qualified url
                    // so display only the endpoint and make a hyperlink
                    url = getParsedURL(data);
                    return "<a href='"+data+"' target='_blank' class='text-info'>"+url+"</a>";
                },
                "targets": 0,
            },
            {
                "render": function ( data, type, row ) {
                    // display badge based on http status
                    // green for http status 2XX, orange for 3XX and warning for everything else
                    if (data >= 200 && data < 300) {
                        return "<span class='badge badge-pills badge-success'>"+data+"</span>";
                    }
                    else if (data >= 300 && data < 400) {
                        return "<span class='badge badge-pills badge-warning'>"+data+"</span>";
                    }
                    else if (data == 0){
                        // datatable throws error when no data is returned
                        return "";
                    }
                    return "<span class='badge badge-pills badge-danger'>"+data+"</span>";

                },
                "targets": 1,
            },
            {
                "render": function ( data, type, row ) {
                    if (data){
                        return htmlEncode(data);
                    }
                    return "";
                },
                "targets": 4,
            },
        ],
        drawCallback: function () {
            $('.t-dot').tooltip({ template: '<div class="tooltip status" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>' })
            $('.dataTables_wrapper table').removeClass('table-striped');
        }
    });
});


// span values function will seperate the values by comma and put badge around it
function span_values(data, color)
{
    var badge = "<span class='badge badge-pill badge-"+color+" m-1'>";
    var data_with_span ="";
    data.split(/\s*,\s*/).forEach(function(split_vals) {
        data_with_span+=badge + split_vals + "</span>";
    });
    return data_with_span;
}
</script>
{% endblock page_level_script %}
